"""
Phase 10: Return Channel Re-emergence (2022-2024)
===================================================
Tests whether the demographic-income balance channel re-emerges as rates
normalize post-QE. Produces:
  Table 15: Rolling 10-year window Z₁ on income balance
  Table 16: QE regime interaction
  Table 17: Mechanism chain pre/post-QE
  Table 18: Safe vs non-safe issuer heterogeneity
  Figure 5: Rolling Z₁ + rate dispersion
"""

import pandas as pd
import numpy as np
from pathlib import Path
import sys
import warnings
warnings.filterwarnings('ignore')

PROJECT_DIR = Path(__file__).resolve().parent.parent
ROOT_DIR = PROJECT_DIR.parent
sys.path.insert(0, str(ROOT_DIR / "multilateral" / "src"))
from model import PanelGLS

DATA = PROJECT_DIR / "data" / "processed"
OUT_TABLES = PROJECT_DIR / "output" / "tables"
OUT_FIGURES = PROJECT_DIR / "output" / "figures"
OUT_TABLES.mkdir(parents=True, exist_ok=True)
OUT_FIGURES.mkdir(parents=True, exist_ok=True)

DEMO_VARS = ['Z_1', 'Z_2', 'Z_3']
EBA_CONTROLS = ['fiscal_bal_gdp', 'nfa_gdp_lag', 'log_rel_opw', 'kaopen']


def available_controls(df, controls=None, min_nonmissing=20):
    """Return controls that have enough non-missing obs in this subsample."""
    if controls is None:
        controls = EBA_CONTROLS
    return [c for c in controls if c in df.columns and df[c].notna().sum() >= min_nonmissing]


def stars(p):
    if p < 0.01: return '***'
    if p < 0.05: return '**'
    if p < 0.1: return '*'
    return ''


def fmt(val, se, p):
    return f"{val:.4f}{stars(p)}", f"({se:.4f})"


def run_gls(df, y_var, x_vars, label, min_obs=50):
    cols = [y_var] + x_vars + ['iso3', 'year']
    sub = df[cols].dropna()
    if len(sub) < min_obs:
        print(f"  SKIP {label}: only {len(sub)} obs (need {min_obs})")
        return None

    gls = PanelGLS()
    gls.fit(sub[y_var].values, sub[x_vars].values,
            sub['iso3'].values, sub['year'].values)

    result = {
        'model': label, 'dep_var': y_var,
        'n_obs': gls.n_obs, 'n_countries': gls.n_countries,
        'r_squared': gls.r_squared, 'rho': gls.rho,
    }
    for i, name in enumerate(x_vars):
        result[f'{name}_coef'] = gls.beta[i]
        result[f'{name}_se'] = gls.se[i]
        result[f'{name}_p'] = gls.pvalues[i]

    print(f"\n  {label} (N={gls.n_obs}, R²={gls.r_squared:.4f})")
    for i, name in enumerate(x_vars):
        if 'Z_' in name or 'qe' in name.lower() or 'safe' in name.lower():
            sig = stars(gls.pvalues[i])
            print(f"    {name:25s} {gls.beta[i]:10.4f} ({gls.se[i]:.4f}) {sig}")

    return result


def run_ols(df, y_var, x_vars, label):
    """OLS fallback for small samples."""
    from scipy import stats as sp_stats
    cols = [y_var] + x_vars + ['iso3', 'year']
    sub = df[cols].dropna()
    if len(sub) < 10:
        print(f"  SKIP OLS {label}: only {len(sub)} obs")
        return None
    try:
        y = sub[y_var].values
        X = np.column_stack([sub[v].values for v in x_vars])
        X_c = np.column_stack([np.ones(len(y)), X])
        beta, _, _, _ = np.linalg.lstsq(X_c, y, rcond=None)
        resid = y - X_c @ beta
        n, k = X_c.shape
        s2 = np.sum(resid ** 2) / max(n - k, 1)
        try:
            var_beta = s2 * np.linalg.inv(X_c.T @ X_c)
            se = np.sqrt(np.diag(var_beta))
        except np.linalg.LinAlgError:
            se = np.full(k, np.nan)
        t_stats = beta / np.where(se > 0, se, np.nan)
        pvals = 2 * (1 - sp_stats.t.cdf(np.abs(t_stats), max(n - k, 1)))
        ss_res = np.sum(resid ** 2)
        ss_tot = np.sum((y - np.mean(y)) ** 2)
        r2 = 1 - ss_res / ss_tot if ss_tot > 0 else np.nan

        result = {
            'model': label, 'dep_var': y_var,
            'n_obs': n, 'n_countries': sub['iso3'].nunique(),
            'r_squared': r2, 'rho': np.nan, 'method': 'OLS',
        }
        for i, name in enumerate(x_vars):
            result[f'{name}_coef'] = beta[i + 1]
            result[f'{name}_se'] = se[i + 1]
            result[f'{name}_p'] = pvals[i + 1]

        print(f"\n  {label} [OLS] (N={n}, R²={r2:.4f})")
        for i, name in enumerate(x_vars):
            if 'Z_' in name:
                sig = stars(pvals[i + 1])
                print(f"    {name:25s} {beta[i+1]:10.4f} ({se[i+1]:.4f}) {sig}")
        return result
    except Exception as e:
        print(f"  ERROR OLS {label}: {e}")
        return None


def run_flexible(df, y_var, x_vars, label, min_obs=50):
    """Try PanelGLS first, fall back to OLS if too few obs."""
    result = run_gls(df, y_var, x_vars, label, min_obs=min_obs)
    if result is None:
        print(f"  Falling back to OLS for {label}")
        result = run_ols(df, y_var, x_vars, label)
        if result is not None:
            result['method'] = 'OLS'
    return result


def write_table(results, filename, title, key_vars=None, footer_note=None):
    if not results:
        return

    lines = [f"# {title}\n"]

    if key_vars is None:
        key_vars = []
        for r in results:
            for k in r:
                if k.endswith('_coef'):
                    v = k.replace('_coef', '')
                    if v not in key_vars:
                        key_vars.append(v)

    model_labels = [r['model'] for r in results]
    header = "| Variable | " + " | ".join(model_labels) + " |"
    sep = "|:---|" + "|".join(["---:" for _ in results]) + "|"
    lines.append(header)
    lines.append(sep)

    for var in key_vars:
        coef_row = f"| {var} |"
        se_row = "| |"
        for r in results:
            if f'{var}_coef' in r:
                c, s = fmt(r[f'{var}_coef'], r[f'{var}_se'], r[f'{var}_p'])
                coef_row += f" {c} |"
                se_row += f" {s} |"
            else:
                coef_row += " |"
                se_row += " |"
        lines.append(coef_row)
        lines.append(se_row)

    lines.append("|:---|" + "|".join(["---:" for _ in results]) + "|")
    for stat, key, fmt_str in [('Dep var', 'dep_var', '{}'), ('N', 'n_obs', '{}'),
                                ('R²', 'r_squared', '{:.4f}'),
                                ('Countries', 'n_countries', '{}')]:
        row = f"| {stat} |"
        for r in results:
            row += f" {fmt_str.format(r[key])} |"
        lines.append(row)

    # Show method if any OLS
    if any(r.get('method') == 'OLS' for r in results):
        row = "| Method |"
        for r in results:
            row += f" {r.get('method', 'PanelGLS')} |"
        lines.append(row)

    if footer_note:
        lines.append(f"\n{footer_note}")
    else:
        lines.append("\n*Panel GLS with AR(1) errors. Standard errors in parentheses.*")
        lines.append("*\\*p<0.1, \\*\\*p<0.05, \\*\\*\\*p<0.01*")

    path = OUT_TABLES / filename
    path.write_text('\n'.join(lines))
    print(f"\n  Saved: {path}")


def main():
    print("=" * 70)
    print("PHASE 10: RETURN CHANNEL RE-EMERGENCE")
    print("=" * 70)

    # ── Load and merge data ──────────────────────────────────────────────
    df = pd.read_csv(DATA / "net_gross_panel.csv")
    df = df[df['year'] <= 2024].copy()
    print(f"Net/gross panel: {len(df)} obs, {df['iso3'].nunique()} countries")

    # Merge QE variables from monetary panel
    mon = pd.read_csv(ROOT_DIR / "monetary" / "data" / "processed" / "monetary_panel.csv")
    qe_cols = ['iso3', 'year', 'qe_active', 'qe_country', 'post_qe_tightening']
    qe_cols = [c for c in qe_cols if c in mon.columns]
    mon_qe = mon[qe_cols].drop_duplicates()
    df = df.merge(mon_qe, on=['iso3', 'year'], how='left')

    # Fill QE flags: missing = 0 (non-QE country)
    for col in ['qe_active', 'qe_country', 'post_qe_tightening']:
        if col in df.columns:
            df[col] = df[col].fillna(0)

    # Merge safe_issuer from cliff panel
    cliff = pd.read_csv(ROOT_DIR / "safe_asset_cliff" / "data" / "processed" / "cliff_panel.csv")
    safe_cols = ['iso3', 'year', 'safe_issuer']
    safe_cols = [c for c in safe_cols if c in cliff.columns]
    cliff_safe = cliff[safe_cols].drop_duplicates()
    df = df.merge(cliff_safe, on=['iso3', 'year'], how='left')
    df['safe_issuer'] = df['safe_issuer'].fillna(0)

    # Construct interaction terms
    df['Z_1_x_qe'] = df['Z_1'] * df['qe_active']
    df['Z_1_x_post_qe'] = df['Z_1'] * df['post_qe_tightening']
    df['Z_1_x_safe'] = df['Z_1'] * df['safe_issuer']

    # Per-year dispersions (cross-sectional SD)
    for var, disp_name in [('real_bond_10y', 'rate_dispersion'),
                            ('income_balance_gdp', 'income_dispersion')]:
        if var in df.columns:
            yr_sd = df.groupby('year')[var].std().reset_index()
            yr_sd.columns = ['year', disp_name]
            df = df.merge(yr_sd, on='year', how='left')

    controls = [c for c in EBA_CONTROLS if c in df.columns and df[c].notna().sum() > 200]
    print(f"Controls: {controls}")
    print(f"QE countries: {df[df['qe_country']==1]['iso3'].nunique()}")
    print(f"Safe issuers: {df[df['safe_issuer']==1]['iso3'].nunique()}")

    # ══════════════════════════════════════════════════════════════════════
    # TABLE 15: ROLLING 10-YEAR WINDOW Z₁ ON INCOME BALANCE
    # ══════════════════════════════════════════════════════════════════════
    print("\n" + "=" * 50)
    print("TABLE 15: ROLLING 10-YEAR WINDOW Z₁ ON INCOME BALANCE")
    print("=" * 50)

    dep = 'income_balance_gdp'
    x_vars = DEMO_VARS + controls
    rolling_records = []

    for window_size in [10, 8]:
        for start_year in range(1985, 2016):
            end_year = start_year + window_size - 1
            if end_year > 2024:
                continue
            window = df[(df['year'] >= start_year) & (df['year'] <= end_year)].copy()
            label = f"{start_year}-{end_year}"

            res = run_flexible(window, dep, x_vars, label, min_obs=30)
            if res:
                rolling_records.append({
                    'window': label,
                    'window_size': window_size,
                    'start_year': start_year,
                    'end_year': end_year,
                    'Z_1_coef': res.get('Z_1_coef', np.nan),
                    'Z_1_se': res.get('Z_1_se', np.nan),
                    'Z_1_pval': res.get('Z_1_p', np.nan),
                    'r2': res['r_squared'],
                    'nobs': res['n_obs'],
                    'ncountries': res['n_countries'],
                    'method': res.get('method', 'PanelGLS'),
                })

    rolling_df = pd.DataFrame(rolling_records)

    if len(rolling_df) > 0:
        # Save CSV for figure
        csv_path = OUT_TABLES / "reemergence_rolling_data.csv"
        rolling_df.to_csv(csv_path, index=False)
        print(f"  Saved CSV: {csv_path}")

        # Build markdown table (10-year windows only)
        r10 = rolling_df[rolling_df['window_size'] == 10].copy()
        md_lines = ["# Table 15: Rolling 10-Year Window Z₁ on Income Balance\n"]
        md_lines.append("| Window | Z₁ coef | Z₁ SE | p-value | R² | N | Method |")
        md_lines.append("|--------|--------:|------:|--------:|---:|--:|--------|")
        for _, row in r10.iterrows():
            s = stars(row['Z_1_pval'])
            md_lines.append(
                f"| {row['window']} "
                f"| {row['Z_1_coef']:.3f}{s} "
                f"| {row['Z_1_se']:.3f} "
                f"| {row['Z_1_pval']:.4f} "
                f"| {row['r2']:.3f} "
                f"| {int(row['nobs']):,} "
                f"| {row['method']} |"
            )
        md_lines.append("")
        md_lines.append("*10-year rolling windows. PanelGLS with AR(1) errors where feasible; OLS fallback.*")
        md_lines.append("*\\*p<0.1, \\*\\*p<0.05, \\*\\*\\*p<0.01*")

        md_t15 = "\n".join(md_lines)
        t15_path = OUT_TABLES / "reemergence_rolling_income_balance.md"
        t15_path.write_text(md_t15)
        print(f"  Saved: {t15_path}")

    # ══════════════════════════════════════════════════════════════════════
    # TABLE 16: QE REGIME INTERACTION
    # ══════════════════════════════════════════════════════════════════════
    print("\n" + "=" * 50)
    print("TABLE 16: QE REGIME INTERACTION")
    print("=" * 50)

    results_t16 = []

    # Col 1: Full sample baseline
    r = run_gls(df, dep, DEMO_VARS + controls, '(1) Full baseline')
    if r: results_t16.append(r)

    # Col 2: Full + qe_active + Z_1_x_qe
    x2 = DEMO_VARS + controls + ['qe_active', 'Z_1_x_qe']
    r = run_gls(df, dep, x2, '(2) Full + QE')
    if r: results_t16.append(r)

    # Col 3: QE countries only
    qe_only = df[df['qe_country'] == 1].copy()
    r = run_gls(qe_only, dep, DEMO_VARS + controls, '(3) QE only')
    if r: results_t16.append(r)

    # Col 4: Non-QE countries only
    non_qe = df[df['qe_country'] == 0].copy()
    r = run_gls(non_qe, dep, DEMO_VARS + controls, '(4) Non-QE')
    if r: results_t16.append(r)

    # Col 5: Full + post_qe_tightening + Z_1_x_post_qe
    # Use adaptive controls so 2022-2024 obs aren't dropped
    controls_no_opw = [c for c in controls if c != 'log_rel_opw']
    x5 = DEMO_VARS + controls_no_opw + ['post_qe_tightening', 'Z_1_x_post_qe']
    r = run_gls(df, dep, x5, '(5) Full + post-QE')
    if r: results_t16.append(r)

    # Col 6: Post-2015 only + post_qe_tightening + Z_1_x_post_qe
    post15 = df[df['year'] >= 2015].copy()
    post15_controls = available_controls(post15, controls_no_opw, min_nonmissing=20)
    x6 = DEMO_VARS + post15_controls + ['post_qe_tightening', 'Z_1_x_post_qe']
    r = run_flexible(post15, dep, x6, '(6) Post-2015 + post-QE', min_obs=30)
    if r: results_t16.append(r)

    key_vars_t16 = DEMO_VARS + controls + ['qe_active', 'Z_1_x_qe',
                                             'post_qe_tightening', 'Z_1_x_post_qe']
    write_table(results_t16, "reemergence_qe_interaction.md",
                "Table 16: QE Regime Interaction — Income Balance",
                key_vars=key_vars_t16)

    # ══════════════════════════════════════════════════════════════════════
    # TABLE 17: MECHANISM CHAIN PRE/POST-QE
    # ══════════════════════════════════════════════════════════════════════
    print("\n" + "=" * 50)
    print("TABLE 17: MECHANISM CHAIN PRE/POST-QE")
    print("=" * 50)

    results_t17 = []
    rate_control = ['real_bond_10y']

    # Col 1: Pre-GFC, no rate control
    pre = df[df['year'] <= 2007].copy()
    r = run_gls(pre, dep, DEMO_VARS + controls, '(1) Pre-GFC')
    if r: results_t17.append(r)

    # Col 2: Pre-GFC + real_bond_10y
    r = run_gls(pre, dep, DEMO_VARS + controls + rate_control, '(2) Pre-GFC +rate')
    if r: results_t17.append(r)

    # Col 3: Post-QE (2022-2024), no rate control — small sample, use min_obs=20
    post_qe = df[(df['year'] >= 2022) & (df['year'] <= 2024)].copy()
    post_controls = available_controls(post_qe, controls, min_nonmissing=20)
    print(f"  Post-QE available controls: {post_controls} (from {len(post_qe)} obs)")
    r = run_flexible(post_qe, dep, DEMO_VARS + post_controls, '(3) 2022-24', min_obs=20)
    if r: results_t17.append(r)

    # Col 4: Post-QE + real_bond_10y
    post_rate = [c for c in rate_control if c in post_qe.columns and post_qe[c].notna().sum() >= 10]
    r = run_flexible(post_qe, dep, DEMO_VARS + post_controls + post_rate,
                     '(4) 2022-24 +rate', min_obs=20)
    if r: results_t17.append(r)

    key_vars_t17 = DEMO_VARS + controls + rate_control
    write_table(results_t17, "reemergence_mechanism_chain.md",
                "Table 17: Mechanism Chain — Rate Attenuation Pre-GFC vs Post-QE",
                key_vars=key_vars_t17,
                footer_note=("*Panel GLS with AR(1) where feasible; OLS fallback for small samples.*\n"
                             "*Cols 3-4: 2022-2024 only (~69 obs). Standard errors in parentheses.*\n"
                             "*\\*p<0.1, \\*\\*p<0.05, \\*\\*\\*p<0.01*"))

    # Interpretation
    if len(results_t17) >= 2:
        z1_pre = results_t17[0].get('Z_1_coef', np.nan)
        z1_pre_rate = results_t17[1].get('Z_1_coef', np.nan)
        if abs(z1_pre) > 0.01:
            att = (z1_pre_rate - z1_pre) / z1_pre * 100
            print(f"\n  Pre-GFC attenuation: {att:.0f}%")
    if len(results_t17) >= 4:
        z1_post = results_t17[2].get('Z_1_coef', np.nan)
        z1_post_rate = results_t17[3].get('Z_1_coef', np.nan)
        if abs(z1_post) > 0.01:
            att = (z1_post_rate - z1_post) / z1_post * 100
            print(f"  Post-QE attenuation: {att:.0f}%")

    # ══════════════════════════════════════════════════════════════════════
    # TABLE 18: SAFE VS NON-SAFE ISSUER HETEROGENEITY
    # ══════════════════════════════════════════════════════════════════════
    print("\n" + "=" * 50)
    print("TABLE 18: SAFE VS NON-SAFE ISSUER HETEROGENEITY")
    print("=" * 50)

    results_t18 = []
    post15 = df[df['year'] >= 2015].copy()
    post15_ctrls = available_controls(post15, controls, min_nonmissing=20)
    print(f"  Post-2015 available controls: {post15_ctrls}")

    # Col 1: Non-safe issuers, 2015-2024
    non_safe = post15[post15['safe_issuer'] == 0].copy()
    r = run_flexible(non_safe, dep, DEMO_VARS + post15_ctrls, '(1) Non-safe 15-24', min_obs=30)
    if r: results_t18.append(r)

    # Col 2: Safe issuers, 2015-2024
    safe = post15[post15['safe_issuer'] == 1].copy()
    safe_ctrls = available_controls(safe, controls, min_nonmissing=15)
    r = run_flexible(safe, dep, DEMO_VARS + safe_ctrls, '(2) Safe 15-24', min_obs=30)
    if r: results_t18.append(r)

    # Col 3: Full sample with Z_1_x_safe interaction
    x3 = DEMO_VARS + post15_ctrls + ['safe_issuer', 'Z_1_x_safe']
    r = run_flexible(post15, dep, x3, '(3) Interaction 15-24', min_obs=30)
    if r: results_t18.append(r)

    # Col 4: Non-safe, 2015-2024 + real_bond_10y
    rate_ctrls = [c for c in rate_control if c in non_safe.columns and non_safe[c].notna().sum() >= 10]
    r = run_flexible(non_safe, dep, DEMO_VARS + post15_ctrls + rate_ctrls,
                     '(4) Non-safe +rate', min_obs=20)
    if r: results_t18.append(r)

    key_vars_t18 = DEMO_VARS + controls + ['safe_issuer', 'Z_1_x_safe', 'real_bond_10y']
    write_table(results_t18, "reemergence_safe_issuer.md",
                "Table 18: Safe vs Non-Safe Issuer Heterogeneity — Income Balance (2015-2024)",
                key_vars=key_vars_t18)

    # ══════════════════════════════════════════════════════════════════════
    # FIGURE 5: ROLLING Z₁ + RATE DISPERSION
    # ══════════════════════════════════════════════════════════════════════
    print("\n" + "=" * 50)
    print("FIGURE 5: ROLLING Z₁ + RATE DISPERSION")
    print("=" * 50)

    if len(rolling_df) > 0:
        import matplotlib
        matplotlib.use('Agg')
        import matplotlib.pyplot as plt

        r10 = rolling_df[rolling_df['window_size'] == 10].copy()

        if len(r10) > 0:
            fig, ax1 = plt.subplots(figsize=(12, 6))

            # Left axis: rolling Z₁ coefficient with 95% CI
            mid_years = (r10['start_year'] + r10['end_year']) / 2
            z1_vals = r10['Z_1_coef'].values
            z1_se = r10['Z_1_se'].values
            ci_lo = z1_vals - 1.96 * z1_se
            ci_hi = z1_vals + 1.96 * z1_se

            ax1.plot(mid_years, z1_vals, 'b-o', linewidth=2, markersize=5,
                     label='Z₁ coefficient (income balance)')
            ax1.fill_between(mid_years, ci_lo, ci_hi, alpha=0.2, color='blue',
                             label='95% CI')
            ax1.axhline(0, color='black', linewidth=0.5)
            ax1.set_xlabel('Window Midpoint Year', fontsize=12)
            ax1.set_ylabel('Z₁ Coefficient on Income Balance', color='blue', fontsize=12)
            ax1.tick_params(axis='y', labelcolor='blue')

            # Right axis: cross-sectional rate dispersion
            if 'rate_dispersion' in df.columns:
                rate_disp = df.groupby('year')['real_bond_10y'].std().reset_index()
                rate_disp.columns = ['year', 'rate_sd']
                rate_disp = rate_disp[(rate_disp['year'] >= 1985) &
                                      (rate_disp['year'] <= 2024)]

                ax2 = ax1.twinx()
                ax2.plot(rate_disp['year'], rate_disp['rate_sd'], 'r--s',
                         linewidth=1.5, markersize=4, alpha=0.7,
                         label='Rate dispersion (SD)')
                ax2.set_ylabel('Cross-Section Rate SD (pp)', color='red', fontsize=12)
                ax2.tick_params(axis='y', labelcolor='red')

            # QE era shading
            ax1.axvspan(2009, 2021, alpha=0.1, color='gray', label='QE era (approx)')

            # Combine legends
            lines1, labels1 = ax1.get_legend_handles_labels()
            if 'rate_dispersion' in df.columns:
                lines2, labels2 = ax2.get_legend_handles_labels()
                ax1.legend(lines1 + lines2, labels1 + labels2,
                           loc='upper left', fontsize=9)
            else:
                ax1.legend(loc='upper left', fontsize=9)

            ax1.set_title('Rolling Z₁ on Income Balance and Cross-Sectional Rate Dispersion',
                          fontsize=13)
            ax1.grid(True, alpha=0.3)
            plt.tight_layout()

            fig_path = OUT_FIGURES / "reemergence_rolling_z1.png"
            plt.savefig(fig_path, dpi=150, bbox_inches='tight')
            plt.close()
            print(f"  Saved: {fig_path}")

    # ── Summary ──────────────────────────────────────────────────────────
    print("\n" + "=" * 70)
    print("SUMMARY")
    print("=" * 70)

    if len(rolling_df) > 0:
        r10 = rolling_df[rolling_df['window_size'] == 10]
        if len(r10) > 0:
            first_w = r10.iloc[0]
            last_w = r10.iloc[-1]
            print(f"  Rolling Z₁ (10yr): {first_w['window']}={first_w['Z_1_coef']:.1f} "
                  f"(p={first_w['Z_1_pval']:.3f}) → "
                  f"{last_w['window']}={last_w['Z_1_coef']:.1f} "
                  f"(p={last_w['Z_1_pval']:.3f})")
            if last_w['Z_1_pval'] < 0.10 and first_w['Z_1_pval'] > 0.10:
                print("  → EVIDENCE of re-emergence")
            elif last_w['Z_1_pval'] < first_w['Z_1_pval']:
                print("  → Z₁ p-value declining (trending toward significance)")

    print("\nPhase 10 complete.")


if __name__ == '__main__':
    main()
